package core;

import principal.EstandarxDLG;
import estandarx.ParametrosSalida;
import funciones.DLG;
import funciones.MetodoMaxVerosimilitud;
import funciones.MetodoMomentos;
import funciones.MetodoPercentiles;
/**
 * Clase principal (logica)que implementa
 * los metodos para calcular los parametros DLG
 * por cualquiera de los tres metodos, y asi poder
 * ser implementada en otras clases.
 */
public class ModuloDLG {

	public ParametrosSalida salida = new ParametrosSalida();

	public MetodoMomentos MMomentos;
	public MetodoPercentiles MPercentiles;
	public MetodoMaxVerosimilitud MMaximav;
	public DLG distribucion=new DLG();
	volatile public Thread hiloActual;//pertenece a un metodo AG
	
	public boolean primeravez=true;
	private static final int MOMENTOS=1;	
	private static final int MAXVEROSIMILITUD=2;
	private static final int PERCENTILES=3;

	public double maximo=2;
	public double minimo=-0.2499;

	public int METODOACTUAL=MOMENTOS;

	public ModuloDLG(EstandarxDLG padre){
		MMomentos = new MetodoMomentos(padre);
		MPercentiles = new MetodoPercentiles(padre);
		MMaximav = new MetodoMaxVerosimilitud(padre);
	}

	public ModuloDLG(EstandarxDLG padre,double min, double max){
		MMomentos = new MetodoMomentos(padre);
		MPercentiles = new MetodoPercentiles(padre);
		MMaximav = new MetodoMaxVerosimilitud(padre);
		maximo=max;
		minimo=min;
	}

//////CONSOLA
	public ModuloDLG(){
		MMomentos = new MetodoMomentos();
		MPercentiles = new MetodoPercentiles();
		MMaximav = new MetodoMaxVerosimilitud();
	}

	public ModuloDLG(double min, double max){
		MMomentos = new MetodoMomentos();
		MPercentiles = new MetodoPercentiles();
		MMaximav = new MetodoMaxVerosimilitud();
		maximo=max;
		minimo=min;
	}

	public void cancelar() {
		hiloActual.interrupt();
	}

	public void evaluar(double muestras[], int metodo, 
			double ErrorEsperado, int  poblacion,
			int  generaciones, double ProbMutacion, double ProbCruce)  
	{
		try {
			METODOACTUAL=metodo;
			
			if(metodo==MOMENTOS){
				MMomentos.calcularMomentos(muestras);
				MMomentos.generaciones=generaciones;
				MMomentos.poblacion=poblacion;
				MMomentos.probabilidadCruce=ProbCruce;
				MMomentos.probabilidadMutacion=ProbMutacion;
				MMomentos.valorMax=maximo;
				MMomentos.valorMin=minimo;
				MMomentos.errorMax=ErrorEsperado;

				hiloActual=new Thread(MMomentos);
				hiloActual.start();
				
//				if(primeravez){
//					hiloActual.join();
//					primeravez=false;
//					hiloActual=null;
//					}

				/*
					MMomentos.ajustarLambdas(MMomentos.mejorcromo);
					salida.lambda1=resultado[0]=MMomentos.la1;
					salida.lambda2=resultado[1]=MMomentos.la2;
					salida.lambda3=resultado[2]=MMomentos.la3;
					salida.lambda4=resultado[3]=MMomentos.la4;
					salida.errorReal=resultado[4]=MMomentos.errorMaxDePoblacion;
				 */	
			}
			else if(metodo==PERCENTILES){
				MPercentiles.CalcularRhos(muestras);
				MPercentiles.generaciones=generaciones;
				MPercentiles.poblacion=poblacion;
				MPercentiles.probabilidadCruce=ProbCruce;
				MPercentiles.probabilidadMutacion=ProbMutacion;
				MPercentiles.valorMax=maximo;
				MPercentiles.valorMin=minimo;
				MPercentiles.errorMax=ErrorEsperado;

				hiloActual=new Thread(MPercentiles);
				hiloActual.start();
				if(primeravez){
					hiloActual.join();
					
					hiloActual=null;
					}

				/*esta ahora en DialogoProgreso
				MPercentiles.ajustarLambdas(MPercentiles.mejorcromo);
				salida.lambda1=resultado[0]=MPercentiles.la1;
				salida.lambda2=resultado[1]=MPercentiles.la2;
				salida.lambda3=resultado[2]=MPercentiles.la3;
				salida.lambda4=resultado[3]=MPercentiles.la4;
				salida.errorReal=resultado[4]=MPercentiles.errorMaxDePoblacion;
				 */
			}
			else if(metodo==MAXVEROSIMILITUD){
				MMaximav.generaciones=generaciones;
				MMaximav.poblacion=poblacion;
				MMaximav.probabilidadCruce=ProbCruce;
				MMaximav.probabilidadMutacion=ProbMutacion;
				MMaximav.valorMax=maximo;
				MMaximav.valorMin=minimo;
				MMaximav.errorMax=ErrorEsperado;
				MMaximav.ajustarTOLERANCIA_P(0.1);
				MMaximav.muestra=muestras;

				hiloActual=new Thread(MMaximav);
				hiloActual.start();
//				if(primeravez){
//					hiloActual.join();
//					primeravez=false;
//					hiloActual=null;
//					}

				/*
				salida.lambda1=resultado[0]=MMaximav.la1;
				salida.lambda2=resultado[1]=MMaximav.la2;
				salida.lambda3=resultado[2]=MMaximav.la3;
				salida.lambda4=resultado[3]=MMaximav.la4;
				salida.errorReal=resultado[4]=MMaximav.errorMaxDePoblacion;
				 */
			}

		} catch (Exception e) {
			System.err.println(e.getMessage());
		}
	}

	/**
	 * otra opcion con metodo de momentos
	 * @param ErrorEsperado
	 * @param poblacion
	 * @param generaciones
	 * @param ProbMutacion
	 * @param ProbCruce
	 * @param media 
	 * @param apuntamiento 
	 * @param varianza 
	 * @param simetria 
	 */
	public void evaluarApartirDeMomentosEstad(double media, double varianza, double apuntamiento, double simetria,
			double ErrorEsperado, int  poblacion,int  generaciones, double ProbMutacion, double ProbCruce)  
	{
		try{
		METODOACTUAL=MOMENTOS;
		
		MMomentos.media=media;
		MMomentos.apuntamiento=apuntamiento;
		MMomentos.varianza=varianza;
		MMomentos.simetria=simetria;
		MMomentos.generaciones=generaciones;
		MMomentos.poblacion=poblacion;
		MMomentos.probabilidadCruce=ProbCruce;
		MMomentos.probabilidadMutacion=ProbMutacion;
		MMomentos.valorMax=maximo;
		MMomentos.valorMin=minimo;
		MMomentos.errorMax=ErrorEsperado;
		hiloActual=new Thread(MMomentos);
		hiloActual.start();
		if(primeravez){
			hiloActual.join();
			primeravez=false;
			hiloActual=null;
			}
		} catch (Exception e) {
			System.err.println(e.getMessage());
		}
	}
	
	public void evaluarApartirDeEstadPercentiles(double mediana, double inter_decil, double tasa_pc, double factor_pc,
			double ErrorEsperado, int  poblacion,int  generaciones, double ProbMutacion, double ProbCruce)
	{
		try{
		METODOACTUAL=PERCENTILES;
		
		MPercentiles.mediana=mediana;
		MPercentiles.inter_decil=inter_decil;
		MPercentiles.tasa_pc=tasa_pc;
		MPercentiles.factor_pc=factor_pc;
		MPercentiles.generaciones=generaciones;
		MPercentiles.poblacion=poblacion;
		MPercentiles.probabilidadCruce=ProbCruce;
		MPercentiles.probabilidadMutacion=ProbMutacion;
		MPercentiles.valorMax=maximo;
		MPercentiles.valorMin=minimo;
		MPercentiles.errorMax=ErrorEsperado;

		hiloActual=new Thread(MPercentiles);
		hiloActual.start();
		if(primeravez){
			hiloActual.join();
			primeravez=false;
			hiloActual=null;
			}
		} catch (Exception e) {
			System.err.println(e.getMessage());
		}
	}

	public Object ObtenerResultadosEnObjeto(){
		return salida;
	}

	public double[]ObtenerMomentos(){
		double resultado[]= new double[4];

		resultado[0]=MMomentos.media;
		resultado[1]=MMomentos.varianza;
		resultado[2]=MMomentos.simetria;
		resultado[3]=MMomentos.apuntamiento;

		return resultado;
	}

	public double[]ObtenerErroresMomentos(){
		double resultado[]= new double[4];
		resultado[0]=MMomentos.errorAlpha3;
		resultado[1]=MMomentos.errorAlpha4;
		return resultado;
	}

	public double[]ObtenerErroresPercentiles(){
		double resultado[]= new double[2]; //erro Rho 3 y Rho4
		resultado[0]=MPercentiles.errorRho3;
		resultado[1]=MPercentiles.errorRho4;
		return resultado;
	}

	public double[]ObtenerRhos(){
		double resultado[]= new double[4];
		resultado[0]=MPercentiles.mediana;
		resultado[1]=MPercentiles.inter_decil;
		resultado[2]=MPercentiles.tasa_pc;
		resultado[3]=MPercentiles.factor_pc;

		return resultado;
	}

	/**
	 * @param alfa:significancia
	 * @param lambda1
	 * @param lambda2
	 * @param lambda3
	 * @param lambda4
	 * @return valor critico
	 */
	public double calcularValorCritico(double alfa,double lambda1,double lambda2,double lambda3,double lambda4){
		distribucion.la1=lambda1;
		distribucion.la2=lambda2;
		distribucion.la3=lambda3;
		distribucion.la4=lambda4;
		return distribucion.calcularValorCritico(alfa);
	}
	//ejemplo
	/*
	public static void main(String arg[]){

		double[] x={-0.300232159,
				-1.277683168,
				0.244257308,
				1.27647354,
				1.198350219,
				1.733133104,
				-2.18358764,
				-0.234181243,
				1.095022526,
				-1.086700649,
				-0.69020416,
				-1.690432327,
				-1.846910891,
				-0.977629497,
				-0.773507054,
				-2.117931217,
				-0.567924872,
				-0.404047569,
				0.134853053,
				-0.365492951,
				-0.32699063,
				-0.370240514,
				1.342641553,
				-0.085284455,
				-0.186157649,
				-0.513207397,
				1.972211976,
				0.865672973,
				2.375654731,
				-0.654906671};

		ModuloDLG dlg= new ModuloDLG ();

		double lmomentos[]=dlg.evaluar(x,1, 1.0E-15, 200,20000, 0.6,0.03);
		double lpercentiles[]=dlg.evaluar(x,3, 1.0E-15, 100,20000, 0.025,0.5);
		double lmaximav[]=dlg.evaluar(x,2, 1.0E-151, 50,1000, 0.6,0.03);
		//tambien se pude en obtener los resultados en un objeto en lugar de una cadena de doubles
		// ParametrosSalida sal = moduloDLG.ObtenerResultadosEnObjeto();

		System.out.println("Por MOMENTOS:");
		System.out.println();
		System.out.println("lambda 1: "+lmomentos[0]);
		System.out.println("lambda 2: "+lmomentos[1]);
		System.out.println("lambda 3: "+lmomentos[2]);
		System.out.println("lambda 4: "+lmomentos[3]);
		System.out.println("lambda error: "+lmomentos[4]);
		System.out.println();
		System.out.println();

		System.out.println("Por PERCENTILES:");
		System.out.println();
		System.out.println("lambda 1: "+lpercentiles[0]);
		System.out.println("lambda 2: "+lpercentiles[1]);
		System.out.println("lambda 3: "+lpercentiles[2]);
		System.out.println("lambda 4: "+lpercentiles[3]);
		System.out.println("lambda error: "+lpercentiles[4]);
		System.out.println();
		System.out.println();

		System.out.println("Por maxima Verosimilitud:");
		System.out.println();
		System.out.println("lambda 1: "+lmaximav[0]);
		System.out.println("lambda 2: "+lmaximav[1]);
		System.out.println("lambda 3: "+lmaximav[2]);
		System.out.println("lambda 4: "+lmaximav[3]);
		System.out.println("lambda error: "+lmaximav[4]);
	}*/
}
